<?php

namespace app\admin\controller\ocation;

use app\common\controller\Backend;
use fast\Tree;
use think\Collection;
use think\Db;
use think\exception\PDOException;


/**
 *
 *
 * @icon fa fa-file
 */
class Ocation extends Backend
{

    /**
     * Ocation模型对象
     */
    protected $model = null;
    protected $noNeedRight = ["lists", "lists2", "status", "changeStatus", "export2", "checkName", "listsusers", "lists_community","recyclebin","restore","lists_sq","getCommunityClassInfo"];
    protected $noNeedLogin = ["lists", "lists2", "status", "changeStatus", "export2", "checkName", "listsusers", "lists_community","recyclebin","restore","lists_sq","getCommunityClassInfo"];


    public function _initialize()
    {
        parent::_initialize();
        $this->model = model('Ocation');
        $this->modelValidate = true;
    }

    /**
     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
     */

    /**
     * 获取教学点经纬度（带回退逻辑）
     * 优先级：主教学点 → 子教学点 → 父教学点
     *
     * @param int $ocationId 教学点ID
     * @return array ['longitude' => float, 'latitude' => float] 或 ['longitude' => null, 'latitude' => null]
     */
    public function getOcationCoordinates($ocationId)
    {
        if (!$ocationId) {
            return ['longitude' => null, 'latitude' => null, 'address' => ''];
        }

        // 获取主教学点信息
        $mainOcation = Db::name('ocation')->where('id', $ocationId)->find();
        if (!$mainOcation) {
            return ['longitude' => null, 'latitude' => null, 'address' => ''];
        }

        // 检查主教学点是否有经纬度
        if (!empty($mainOcation['address']) && !empty($mainOcation['longitude']) && !empty($mainOcation['latitude'])) {
            $address = $mainOcation['address'] ?? '';

            // 如果地址为空，通过百度地图API获取
            if (empty($address)) {
                $addressResult = $this->getAddressByCoordinates($mainOcation['longitude'], $mainOcation['latitude']);
                if ($addressResult['success'] && !empty($addressResult['data']['formatted_address'])) {
                    $address = $addressResult['data']['formatted_address'];

                    // 更新数据库中的地址
                    try {
                        Db::name('ocation')->where('id', $ocationId)->update([
                            'address' => $address,
                            'update_time' => time()
                        ]);
                    } catch (\Exception $e) {
                        // 数据库更新失败不影响返回结果
                    }
                }
            }

            return [
                'longitude' => (float)$mainOcation['longitude'],
                'latitude' => (float)$mainOcation['latitude'],
                'address' => $address,
            ];
        }

        // 主教学点没有经纬度，递归遍历所有子教学点（包括子教学点的子教学点）
        $validChildOcation = $this->findValidChildOcation($ocationId);

        if ($validChildOcation) {
            $address = $validChildOcation['address'] ?? '';

            // 如果地址为空，通过百度地图API获取
            if (empty($address)) {
                $addressResult = $this->getAddressByCoordinates($validChildOcation['longitude'], $validChildOcation['latitude']);
                if ($addressResult['success'] && !empty($addressResult['data']['formatted_address'])) {
                    $address = $addressResult['data']['formatted_address'];

                    // 更新数据库中的地址
                    try {
                        Db::name('ocation')->where('id', $validChildOcation['id'])->update([
                            'address' => $address,
                            'update_time' => time()
                        ]);
                    } catch (\Exception $e) {
                        // 数据库更新失败不影响返回结果
                    }
                }
            }

            return [
                'longitude' => (float)$validChildOcation['longitude'],
                'latitude' => (float)$validChildOcation['latitude'],
                'address' => $address,
            ];
        }

        // 子教学点也没有经纬度，尝试获取父教学点的经纬度
        if (!empty($mainOcation['pid']) && $mainOcation['pid'] > 0) {
            $parentOcation = Db::name('ocation')->where('id', $mainOcation['pid'])->find();
            if ($parentOcation && !empty($parentOcation['address']) && !empty($parentOcation['longitude']) && !empty($parentOcation['latitude'])) {
                $address = $parentOcation['address'] ?? '';

                // 如果地址为空，通过百度地图API获取
                if (empty($address)) {
                    $addressResult = $this->getAddressByCoordinates($parentOcation['longitude'], $parentOcation['latitude']);
                    if ($addressResult['success'] && !empty($addressResult['data']['formatted_address'])) {
                        $address = $addressResult['data']['formatted_address'];

                        // 更新数据库中的地址
                        try {
                            Db::name('ocation')->where('id', $parentOcation['id'])->update([
                                'address' => $address,
                                'update_time' => time()
                            ]);
                        } catch (\Exception $e) {
                            // 数据库更新失败不影响返回结果
                        }
                    }
                }

                return [
                    'longitude' => (float)$parentOcation['longitude'],
                    'latitude' => (float)$parentOcation['latitude'],
                    'address' => $address,
                ];
            }
        }


        // 都没有经纬度，返回空值
        return ['longitude' => null, 'latitude' => null, 'address' => ''];
    }

    /**
     * 递归查找有效的子教学点（包括子教学点的子教学点）
     *
     * @param int $parentId 父教学点ID
     * @return array|null 返回第一个找到的有效教学点，如果没有找到返回null
     */
    private function findValidChildOcation($parentId)
    {
        // 获取所有直接子教学点
        $childOcations = Db::name('ocation')
            ->where('pid', $parentId)
            ->select();

        if (empty($childOcations)) {
            return null;
        }

        // 遍历每个子教学点
        foreach ($childOcations as $childOcation) {
            // 检查当前子教学点是否有有效的经纬度
            if (
                !empty($childOcation['longitude']) && !empty($childOcation['latitude']) &&
                $childOcation['longitude'] != '0' && $childOcation['latitude'] != '0' && $childOcation['address'] != ""
            ) {
                return $childOcation;
            }

            // 如果当前子教学点没有有效经纬度，递归查找它的子教学点
            $validGrandChild = $this->findValidChildOcation($childOcation['id']);
            if ($validGrandChild) {
                return $validGrandChild;
            }
        }

        return null;
    }

    /**
     * 批量获取多个教学点的经纬度
     *
     * @param array $ocationIds 教学点ID数组
     * @return array 格式：[ocation_id => ['longitude' => float, 'latitude' => float], ...]
     */
    public function getBatchOcationCoordinates($ocationIds)
    {
        $result = [];

        if (empty($ocationIds) || !is_array($ocationIds)) {
            return $result;
        }

        foreach ($ocationIds as $ocationId) {
            $result[$ocationId] = $this->getOcationCoordinates($ocationId);
        }

        return $result;
    }

    /**
     * 静态方法：获取教学点经纬度（可在其他地方直接调用）
     *
     * @param int $ocationId 教学点ID
     * @return array ['longitude' => float, 'latitude' => float] 或 ['longitude' => null, 'latitude' => null]
     */
    public static function getCoordinates($ocationId)
    {
        $instance = new self();
        return $instance->getOcationCoordinates($ocationId);
    }

    /**
     * 通过经纬度获取详细地址信息（调用百度地图API）
     *
     * @param float $longitude 经度
     * @param float $latitude 纬度
     * @return array 地址信息
     */
    public function getAddressByCoordinates($longitude, $latitude)
    {
        if (!$longitude || !$latitude) {
            return [
                'success' => false,
                'message' => '经纬度参数无效',
                'data' => null
            ];
        }

        // 获取百度地图API配置（从ai配置文件中获取）
        $aiConfig = config('ai');
        $baiduConfig = $aiConfig['baidu_map'] ?? [];

        // 优先使用服务端API密钥
        $apiKey = $baiduConfig['api_key_server'] ?? $baiduConfig['api_key'] ?? '';

        if (empty($apiKey)) {
            return [
                'success' => false,
                'message' => '百度地图API密钥未配置',
                'data' => null
            ];
        }

        // 百度地图逆地理编码API URL
        $apiUrl = $baiduConfig['api_urls']['reverse_geocoding'] ?? 'https://api.map.baidu.com/reverse_geocoding/v3/';

        // 获取默认请求参数
        $defaultParams = $baiduConfig['default_params'] ?? [
            'output' => 'json',
            'coordtype' => 'wgs84ll',
            'extensions_poi' => 1,
            'extensions_road' => true,
            'extensions_town' => true
        ];

        $params = array_merge($defaultParams, [
            'ak' => $apiKey,
            'location' => $latitude . ',' . $longitude,
        ]);

        $requestUrl = $apiUrl . '?' . http_build_query($params);

        try {
            // 获取请求配置
            $requestConfig = $baiduConfig['request_config'] ?? [
                'timeout' => 10,
                'user_agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
                'ssl_verify' => false
            ];

            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $requestUrl);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_TIMEOUT, $requestConfig['timeout']);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $requestConfig['ssl_verify']);
            curl_setopt($ch, CURLOPT_USERAGENT, $requestConfig['user_agent']);

            $response = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $error = curl_error($ch);
            curl_close($ch);

            if ($error) {
                return [
                    'success' => false,
                    'message' => 'cURL错误: ' . $error,
                    'data' => null
                ];
            }

            if ($httpCode !== 200) {
                return [
                    'success' => false,
                    'message' => 'API请求失败，HTTP状态码: ' . $httpCode,
                    'data' => null
                ];
            }

            $result = json_decode($response, true);

            if (!$result || $result['status'] !== 0) {
                return [
                    'success' => false,
                    'message' => '百度地图API返回错误: ' . ($result['message'] ?? '未知错误'),
                    'data' => null
                ];
            }

            // 解析地址信息
            $addressInfo = $this->parseBaiduAddressResult($result['result']);

            return [
                'success' => true,
                'message' => '地址获取成功',
                'data' => $addressInfo
            ];
        } catch (\Exception $e) {
            return [
                'success' => false,
                'message' => '获取地址异常: ' . $e->getMessage(),
                'data' => null
            ];
        }
    }

    /**
     * 解析百度地图API返回的地址结果
     *
     * @param array $result 百度地图API返回的result部分
     * @return array 格式化的地址信息
     */
    private function parseBaiduAddressResult($result)
    {
        $addressComponent = $result['addressComponent'] ?? [];
        $formattedAddress = $result['formatted_address'] ?? '';
        $pois = $result['pois'] ?? [];
        $roads = $result['roads'] ?? [];

        // 基本地址信息
        $addressInfo = [
            'formatted_address' => $formattedAddress,
            'province' => $addressComponent['province'] ?? '',
            'city' => $addressComponent['city'] ?? '',
            'district' => $addressComponent['district'] ?? '',
            'street' => $addressComponent['street'] ?? '',
            'street_number' => $addressComponent['street_number'] ?? '',
            'country' => $addressComponent['country'] ?? '中国',
            'country_code' => $addressComponent['country_code'] ?? 0,
            'adcode' => $addressComponent['adcode'] ?? '',
        ];

        // 附近POI信息
        $nearbyPois = [];
        foreach (array_slice($pois, 0, 5) as $poi) { // 只取前5个POI
            $nearbyPois[] = [
                'name' => $poi['name'] ?? '',
                'address' => $poi['addr'] ?? '',
                'distance' => $poi['distance'] ?? 0,
                'direction' => $poi['direction'] ?? '',
                'tag' => $poi['tag'] ?? '',
                'tel' => $poi['tel'] ?? ''
            ];
        }

        // 附近道路信息
        $nearbyRoads = [];
        foreach (array_slice($roads, 0, 3) as $road) { // 只取前3条道路
            $nearbyRoads[] = [
                'name' => $road['name'] ?? '',
                'distance' => $road['distance'] ?? 0,
                'direction' => $road['direction'] ?? ''
            ];
        }

        $addressInfo['nearby_pois'] = $nearbyPois;
        $addressInfo['nearby_roads'] = $nearbyRoads;

        return $addressInfo;
    }

    /**
     * 获取教学点的完整位置信息（经纬度 + 地址）
     *
     * @param int $ocationId 教学点ID
     * @return array 包含经纬度和地址信息
     */
    public function getOcationLocationInfo($ocationId)
    {
        // 获取经纬度
        $coordinates = $this->getOcationCoordinates($ocationId);

        $result = [
            'ocation_id' => $ocationId,
            'coordinates' => $coordinates,
            'address_info' => null,
            'has_location' => false
        ];

        // 如果有经纬度，获取地址信息
        if ($coordinates['longitude'] && $coordinates['latitude']) {
            $addressResult = $this->getAddressByCoordinates($coordinates['longitude'], $coordinates['latitude']);

            $result['address_info'] = $addressResult;
            $result['has_location'] = $addressResult['success'];
        }

        return $result;
    }

    /**
     * 批量获取多个教学点的完整位置信息
     *
     * @param array $ocationIds 教学点ID数组
     * @return array 格式：[ocation_id => location_info, ...]
     */
    public function getBatchOcationLocationInfo($ocationIds)
    {
        $result = [];

        if (empty($ocationIds) || !is_array($ocationIds)) {
            return $result;
        }

        foreach ($ocationIds as $ocationId) {
            $result[$ocationId] = $this->getOcationLocationInfo($ocationId);

            // 添加延迟，避免API调用过于频繁
            usleep(100000); // 0.1秒延迟
        }

        return $result;
    }

    /**
     * 递归检查教学点的所有子节点是否有教室
     *
     * @param int $parentId 父教学点ID
     * @param array $dataMap 教学点数据映射
     * @return bool 如果有教室返回true，否则返回false
     */
    private function hasClassroomInChildren($parentId, $dataMap)
    {
        foreach ($dataMap as $item) {
            if ($item['pid'] == $parentId) {
                // 如果子节点是教室（address_lv_octionlevel = 4），返回true
                if ($item['address_lv_octionlevel'] == 4) {
                    return true;
                }

                // 递归检查子节点的子节点
                if ($this->hasClassroomInChildren($item['id'], $dataMap)) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * 智能过滤教学点数据，移除没有教室的一二级教学点及其无效的上级节点
     *
     * @param array $data 原始教学点数据
     * @return array 过滤后的教学点数据
     */
    private function filterOcationsWithClassrooms($data)
    {
        // 将数据转换为以ID为键的关联数组，便于查找
        $dataMap = [];
        foreach ($data as $item) {
            $dataMap[$item['id']] = $item;
        }

        // 标记有效的教学点
        $validIds = [];

        // 第一步：标记所有教室（address_lv_octionlevel = 4）为有效
        foreach ($data as $item) {
            if ($item['address_lv_octionlevel'] == 4) {
                $validIds[$item['id']] = true;
            }
        }

        // 第二步：标记有教室的一二级教学点为有效
        foreach ($data as $item) {
            if ($item['address_lv_octionlevel'] == 1 || $item['address_lv_octionlevel'] == 2) {
                if ($this->hasClassroomInChildren($item['id'], $dataMap)) {
                    $validIds[$item['id']] = true;
                }
            }
        }

        // 第三步：标记其他级别的教学点（如果有有效子节点）
        foreach ($data as $item) {
            if (
                !isset($validIds[$item['id']]) &&
                $item['address_lv_octionlevel'] != 1 &&
                $item['address_lv_octionlevel'] != 2 &&
                $item['address_lv_octionlevel'] != 4
            ) {
                if ($this->hasValidChildrenInData($item['id'], $dataMap, $validIds)) {
                    $validIds[$item['id']] = true;
                }
            }
        }

        // 第四步：向上标记有效节点的所有父节点
        foreach ($validIds as $id => $valid) {
            $this->markParentsAsValid($id, $dataMap, $validIds);
        }

        // 第五步：返回所有有效的教学点
        $filteredData = [];
        foreach ($data as $item) {
            if (isset($validIds[$item['id']])) {
                $filteredData[] = $item;
            }
        }

        return $filteredData;
    }

    /**
     * 检查指定教学点在给定数据中是否有有效的子节点
     *
     * @param int $parentId 父教学点ID
     * @param array $dataMap 教学点数据映射
     * @param array $validIds 已标记为有效的ID数组
     * @return bool
     */
    private function hasValidChildrenInData($parentId, $dataMap, $validIds)
    {
        foreach ($dataMap as $item) {
            if ($item['pid'] == $parentId) {
                // 如果子节点已经被标记为有效，返回true
                if (isset($validIds[$item['id']])) {
                    return true;
                }

                // 如果子节点是教室，返回true
                if ($item['address_lv_octionlevel'] == 4) {
                    return true;
                }

                // 递归检查子节点的子节点
                if ($this->hasValidChildrenInData($item['id'], $dataMap, $validIds)) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * 向上标记有效节点的所有父节点为有效
     *
     * @param int $id 当前节点ID
     * @param array $dataMap 教学点数据映射
     * @param array &$validIds 有效ID数组（引用传递）
     */
    private function markParentsAsValid($id, $dataMap, &$validIds)
    {
        if (isset($dataMap[$id]) && $dataMap[$id]['pid'] > 0) {
            $parentId = $dataMap[$id]['pid'];
            if (!isset($validIds[$parentId])) {
                $validIds[$parentId] = true;
                // 递归标记父节点的父节点
                $this->markParentsAsValid($parentId, $dataMap, $validIds);
            }
        }
    }

    /**
     * 获取指定教学点的所有子教学点ID（递归）
     *
     * @param int $parentId 父教学点ID
     * @return array 所有子教学点ID数组
     */
    public function getChildOcationIds($parentId, $includeSelf = false)
    {
        $childIds = [];
        // 支持逗号分隔字符串或数组
        if (is_string($parentId) && strpos($parentId, ',') !== false) {
            $parentId = explode(',', $parentId);
        }
        // 获取直接子教学点
        $directChildren = Db::name('ocation')
            ->where('pid', 'in', (array)$parentId)
            ->where('status', 1)
            ->column('id');
        foreach ($directChildren as $childId) {
            $childIds[] = $childId;
            // 递归获取子教学点的子教学点
            $grandChildIds = $this->getChildOcationIds($childId);
            $childIds = array_merge($childIds, $grandChildIds);
        }
        if ($includeSelf) {
            foreach ((array)$parentId as $pid) {
                array_unshift($childIds, $pid);
            }
        }
        return $childIds;
    }

    /**
     * 根据教学点ID获取关联的班级ID列表
     *
     * @param int $ocationId 教学点ID
     * @return array 班级ID数组
     */
    public function getClassesIdByOcationId($ocationId)
    {
        if (!$ocationId) {
            return [];
        }

        // 获取教学点及其所有子教学点ID
        $ocationIds = $this->getChildOcationIds($ocationId, true);

        // 根据教学点ID获取关联的班级ID
        $classesIds = Db::name('eb_classes')
            ->where('ocation_id', 'in', $ocationIds)
            ->where('status', 1)
            ->column('id');

        return $classesIds ?: [];
    }

    /**
     * 快捷搜索方法
     */
    public function quickSearch()
    {
        // 获取搜索参数
        $searchValue = $this->request->get('search', '');
        $searchType = (is_numeric($searchValue)) ? 'id' : 'text'; // id 或 text

        // 获取分页参数
        $page = intval($this->request->get('page', 1));
        $limit = intval($this->request->get('limit', 30));
        $offset = ($page - 1) * $limit;

        // 获取其他过滤参数
        $relType = $this->request->get('rel_type', '');
        $relId = $this->request->get('rel_id', '');
        $cityId = $this->request->get('city_id', '');
        $schoolId = $this->request->get('school_id', '');

        // 记录搜索日志
        file_put_contents(
            $_SERVER["DOCUMENT_ROOT"] . "/../runtime/log/ocation_search.log",
            date('Y-m-d H:i:s') . " - 教学点搜索: 搜索值={$searchValue}, 类型={$searchType}\n",
            FILE_APPEND
        );

        try {
            $result = $this->searchOcations($searchValue, $searchType, $relType, $relId, $cityId, $schoolId, $offset, $limit);

            // 返回与index方法相同的格式
            return json([
                'total' => $result['total'],
                'rows' => $result['rows']
            ]);
        } catch (\Exception $e) {
            // 记录错误日志
            file_put_contents(
                $_SERVER["DOCUMENT_ROOT"] . "/../runtime/log/ocation_search.log",
                date('Y-m-d H:i:s') . " - 教学点搜索错误: " . $e->getMessage() . "\n",
                FILE_APPEND
            );

            // 返回与index方法相同的格式
            return json([
                'total' => 0,
                'rows' => []
            ]);
        }
    }

    /**
     * 搜索教学点
     */
    private function searchOcations($searchValue, $searchType, $relType, $relId, $cityId, $schoolId, $offset, $limit)
    {
        // 记录搜索参数用于调试
        file_put_contents(
            $_SERVER["DOCUMENT_ROOT"] . "/../runtime/log/ocation_search_debug.log",
            date('Y-m-d H:i:s') . " - 搜索参数: searchValue={$searchValue}, searchType={$searchType}, relType={$relType}, relId={$relId}, cityId={$cityId}, schoolId={$schoolId}, offset={$offset}, limit={$limit}\n",
            FILE_APPEND
        );

        try {
            // 构建where条件数组
            $where = [];

            // 基础条件：只查询正常状态的教学点
            $where['status'] = 1;

            // 应用权限控制
            if (isset($_SESSION['think']['admin']['group_id'])) {
                $groupId = $_SESSION['think']['admin']['group_id'];
                if (in_array($groupId, [2, 8]) && !empty($_SESSION['think']['admin']['city_id'])) {
                    $where['city_id'] = $_SESSION['think']['admin']['city_id'];
                }
            }

            // 处理关联类型
            if (!empty($relType)) {
                $where['rel_type'] = $relType;
            }

            // 处理关联ID的优先级：relId > schoolId > cityId
            if (!empty($relId)) {
                // 如果有明确的relId，直接使用
                $where['rel_id'] = $relId;
            } elseif (!empty($schoolId)) {
                // 如果有schoolId，使用schoolId
                //$where['rel_id'] = $schoolId;
            } elseif (!empty($cityId)) {
                // 如果只有cityId，根据城市ID获取该城市下的所有学校ID
                $schoolIds = Db::name('eb_school')
                    ->where('city_id', $cityId)
                    ->where('status', 1)
                    ->column('id');

                if (!empty($schoolIds)) {
                    $where['rel_id'] = ['in', $schoolIds];
                } else {
                    // 如果该城市下没有学校，返回空结果
                    return ['rows' => [], 'total' => 0];
                }
            }

            // 构建搜索条件
            if (!empty($searchValue)) {
                if ($searchType === 'id') {
                    // ID精确搜索
                    $where['id'] = intval($searchValue);
                } else {
                    // 教学点名称模糊搜索
                    $where['name'] = ['like', '%' . $searchValue . '%'];
                }
            }

            // 记录where条件用于调试
            file_put_contents(
                $_SERVER["DOCUMENT_ROOT"] . "/../runtime/log/ocation_search_debug.log",
                date('Y-m-d H:i:s') . " - Where条件: " . json_encode($where, JSON_UNESCAPED_UNICODE) . "\n",
                FILE_APPEND
            );

            // 获取总数
            $total = $this->model->where($where)->count();

            // 获取列表数据
            $list = $this->model->where($where)
                ->order('id', 'asc')
                ->limit($offset, $limit)
                ->select();
            $list = Collection($list)->toArray();
            foreach($list as $key=>$value){
                $list[$key]['school_location_type']=($value['school_location_type']!="")?$value['school_location_type']:($value['rel_type']==1?1:2);
            }
        } catch (\Exception $e) {
            // 记录错误日志
            $logPath = RUNTIME_PATH . 'log/ocation_search_error.log';
            file_put_contents(
                $logPath,
                date('Y-m-d H:i:s') . " - 教学点搜索SQL错误: " . $e->getMessage() . "\n" .
                    "File: " . $e->getFile() . " (" . $e->getLine() . ")\n" .
                    "Trace: " . $e->getTraceAsString() . "\n\n",
                FILE_APPEND
            );
            return ['rows' => [], 'total' => 0];
        }

        // 转换为数组
        $listArray = is_array($list) ? $list : $list->toArray();

        // 格式化数据（仿照index方法的处理逻辑）
        $formattedList = $this->formatOcationData($listArray);

        return ['rows' => $formattedList, 'total' => $total];
    }

    /**
     * 格式化教学点数据
     */
    private function formatOcationData($list)
    {
        $data = [];

        foreach ($list as $v) {
            // 处理实体或虚拟状态
            $entvirt = ($v['address_lv_octionlevel'] == 2) ? (($v['entvirt'] == "1") ? "实体" : "虚拟") : "";

            // 处理时间显示
            $endtime = empty($v['starttime']) ? '未设置' : substr($v['starttime'], 0, 10) . " 到 " .
                (empty($v['endtime']) ? '未设置' : substr($v['endtime'], 0, 10));

            // 处理教学点类型
            $ocation_type = model("Ocation")->getOction_typeTextAttr($v['ocation_type']);

            $data[] = [
                'id' => $v['id'],
                'ocation_id' => $v['id'],
                'classes_id' => join(" ", $this->getClassesIdByOcationId($v['id'])),
                'parent' => $v['pid'] ? $v['pid'] : '#',
                'name' => $v['name'],
                'level' => 0, // 搜索结果不需要层级显示
                'type' => $v['type'],
                'status' => $v['status'],
                'haschild' => 0, // 搜索结果不显示子节点
                'address' => $v['address'],
                'weekdays' => $v['weekdays'],
                'ocation_type' => $ocation_type,
                'entvirt' => $entvirt,
                'endtime' => $endtime,
                'address_lv_octionlevel' => model("Ocation")->getAddress_lv_octionlevel_TextAttr($v['address_lv_octionlevel']),
                'school_location_type' => model("Ocation")->getSchool_location_typeTextAttr($v['school_location_type']),
            ];
        }

        return $data;
    }

    /**
     * 查看
     */
    public function index()
    {
        //设置过滤方法
        $this->request->filter(['strip_tags']);
        // 修复语法错误和潜在的"Undefined array key"问题
        $relId = ($this->request->get("rel_id") > 0) ? $this->request->get("rel_id") : (isset($_SESSION['think']['admin']['rel_id']) ? $_SESSION['think']['admin']['rel_id'] : 0);
        $relType = ($this->request->get("rel_type") > 0) ? $this->request->get("rel_type") : (isset($_SESSION['think']['admin']['rel_type']) ? $_SESSION['think']['admin']['rel_type'] : '');
        $city_id = $this->request->get("city_id") ?: (isset($_SESSION['think']['admin']['city_id']) ? $_SESSION['think']['admin']['city_id'] : '');
        $school_id = $this->request->get("school_id") ?: (isset($_SESSION['think']['admin']['school_id']) ? $_SESSION['think']['admin']['school_id'] : '');


        if ($this->request->isAjax()) {
            //如果发送的来源是Selectpage，则转发到Selectpage
            if ($this->request->request('keyField')) {
                return $this->selectpage();
            }

            // 处理快捷搜索请求
            if ($this->request->get('search') !== null&&$this->request->get('search') !== "") {
                return $this->quickSearch();
            }
            $this->fixTeachingPointHierarchy();


            // 如果 relId 为空或0，使用 city_id 和 school_id 参数
            if (empty($relId) || $relId == 0) {
                $m = model("Ocation");
                $m->where("status", "=", 1);
                // 根据 city_id 过滤
                if (!empty($city_id)) {
                    $m = $m->where("city_id", "=", $city_id);
                }

                // 根据 school_id 过滤（使用 rel_id 和 rel_type）
                if (!empty($school_id)) {
                    //$m = $m->where("rel_id", "=", $school_id)->where("rel_type", "=", 1);
                }

                // 添加排序规则，按照weigh字段降序排序，weigh相同时按照id升序排序
                $m->order('weigh', 'desc')->order('id', 'asc');
                $data = $m->select();
            } else if (isset($relType) && ($relType == 1 || $relType == 2)) {
                // 原有逻辑：使用 relType 和 relId
                $m = model("Addresslv")->where("rel_type", "=", $relType)
                    ->where("rel_id", "=", $relId)
                    ->where("status", "=", 1);
                if ($_SESSION['think']['admin']['group_id'] == 2 || $_SESSION['think']['admin']['group_id'] == 8) {
                    $m = $m->where("city_id", "=", $_SESSION['think']['admin']['city_id']);
                }
                if (isset($relType) && $relId > 0) {
                    $m = $m->where("rel_type", "=", $relType)->where("rel_id", "=", $relId);
                }
                $r = $m->select();

                if ($relType == "1" || $relType == "school") {
                    $tablename = "School";
                    $tableN = "eb_school";
                } else {
                    $tablename = "Community";
                    $tableN = "fa_community";
                }
                if ($relId != "") {
                    $r_name = model($tablename)->field("id,name")->where("id", "=", $relId)->select();
                    if (empty($r) && !empty($r_name) && isset($r_name[0]) && isset($r_name[0]['name'])) {
                        $time = date("Y-m-d H:i:s");
                        $data = array(
                            "type" => "file",
                            "pid" => 0,
                            "name" => $r_name[0]['name'],
                            "title" => $r_name[0]['name'],
                            "ismenu" => 0,
                            "create_time" => $time,
                            "update_time" => $time,
                            "status" => 1,
                            "rel_id" => $relId,
                            "rel_type" => $relType,
                        );
                        model("Ocation")->insertUpdate($data, ["rel_id", "rel_type"]);
                    }
                }
                $m = model("Ocation")->where("rel_type", "=", $relType)->where("status", "=", 1);
                if ($relId > 0) {
                    $m->where("rel_id", "=", $relId);
                }

                // 添加城市过滤
                $cityareaId = $this->request->get("city_id");
                if ($cityareaId) {
                    // 根据城市ID获取该城市下的所有学校ID
                    $schoolIds = Db::name('eb_school')
                        ->where('city_id', $cityareaId)
                        ->where('status', 1)
                        ->column('id');

                    if (!empty($schoolIds)) {
                        $m->where("rel_id", "in", $schoolIds);
                    } else {
                        // 如果该城市下没有学校，返回空结果
                        $m->where("id", 0);
                    }
                }

                // 添加学校过滤
                $schoolIdFilter = $this->request->get("school_id");
                if ($schoolIdFilter) {
                    $m->where("rel_id", $schoolIdFilter);
                }

                // 添加排序规则，按照weigh字段降序排序，weigh相同时按照id升序排序
                $m->order('weigh', 'desc')->order('id', 'asc');
                $data = $m->select();
            }
            $data2=collection($data)->toArray();
            foreach($data2 as $key=>$value){
                $data2[$key]['school_location_type']=($value['school_location_type']!="")?$value['school_location_type']:($value['rel_type']==1?1:2);
            }


            //$m->getLastSql();
            // 先过滤掉无效的教学点，然后重新构建树结构
            //$filteredData = $this->filterOcationsWithClassrooms($data);
            $filteredData = $data2;

            $tree = Tree::instance();
            $tree->init($filteredData, 'pid');
            $pid = 0;
            $arr = $tree->getTreeList($tree->getTreeArray($pid), 'name');
            $data = array();
            for ($i = 0; $i < count($arr); $i++) {
                $v = $arr[$i];
                // 只有address_lv_octionlevel=2的才有实体或虚拟状态，其他都为空
                $entvirt = ($v['address_lv_octionlevel'] == 2) ? (($v['entvirt'] == "1") ? "实体" : "虚拟") : "";
                $endtime = empty($v['starttime']) ? '未设置' : substr($v['starttime'], 0, 10) . " 到 " .
                    (empty($v['endtime']) ? '未设置' : substr($v['endtime'], 0, 10));
                $ocation_type = model("Ocation")->getOction_typeTextAttr($v['ocation_type']);
                if (isset($_REQUEST['search'])) {
                    $_REQUEST["search"] = preg_replace("/党/", ".*", $_REQUEST["search"]);
                    if (isset($_REQUEST['search']) && $_REQUEST['search'] != "") {
                        if (!preg_match("/{$_REQUEST["search"]}/Uisx", $v['name'], $match)) {
                            continue;
                        }
                    }
                }
                if ($v['level'] == 0) {
                    $v['name'] = "<span class='lv1'>{$v['name']}</span>";
                }
                if ($v['level'] == 1) {
                    $v['name'] = preg_replace_callback("/^(\&nbsp\;)((?:\s|├|\&nbsp\;|│|├|└)*?)(.*)$/Uisx", function ($em) use ($v) {
                        $aliasDisplay = !empty($v['alias']) ? "&nbsp;<span class='label label-primary v_2_1'>{$v['alias']}</span>" : "";
                        return "{$em[1]}" . str_replace("&nbsp;", "&nbsp;&nbsp;", $em[2]) . "<span class='lv0'>{$em[3]}</span>{$aliasDisplay}";
                    }, $v['name']);
                }

                if ($v['level'] == 2) {
                    $v['name'] = preg_replace_callback("/^(\&nbsp\;)((?:\s|\&nbsp\;|\│|\├|└)*?)(.*)$/Uisx", function ($em) use ($v) {
                        $aliasDisplay = !empty($v['alias']) ? "&nbsp;<span class='label label-primary v_2_2'>{$v['alias']}</span>" : "";
                        return "{$em[1]}" . str_replace("&nbsp;", "&nbsp;&nbsp;", $em[2]) . "<span class='v_2'>{$em[3]}</span>{$aliasDisplay}";
                    }, $v['name']);
                }

                if ($v['level'] == 3) {
                    $v['name'] = preg_replace_callback("/^(\&nbsp\;)((?:\s|\&nbsp\;|\│|\├|└)*?)(.*)$/Uisx", function ($em)  use ($v) {
                        $aliasDisplay = !empty($v['alias']) ? "&nbsp;<span class='label label-primary  v_2_3' '>{$v['alias']}</span>" : "";
                        return "{$em[1]}" . str_replace("&nbsp;", "&nbsp;&nbsp;", $em[2]) . "<span class='lv3'>{$em[3]}</span>{$aliasDisplay}";
                    }, $v['name']);
                }

                if ($v['level'] == 4 || $v['address_lv_octionlevel'] == 4) {
                    $v['name'] = preg_replace_callback("/^(\&nbsp\;)((?:\s|\&nbsp\;|\│|\├|└)*?)(.*)$/Uisx", function ($em) {
                        $em[3] = preg_replace("/lv[0-9]+/", "lv4", $em[3]);
                        return "{$em[1]}" . str_replace("&nbsp;", "&nbsp;&nbsp;", $em[2]) . "{$em[3]}";
                    }, $v['name']);
                    $v['name'] = preg_replace_callback("/^(\s*<span\s+class='lv[0-9]'>)((?:\s|\&nbsp\;|\│|├|├|└)*?)(.*)$/Uisx", function ($em) {
                        $em[1] = preg_replace("/lv[0-9]+/", "lv4", $em[1]);
                        return str_replace("&nbsp;", "&nbsp;&nbsp;", $em[2]) . "{$em[1]}" . "{$em[3]}";
                    }, $v['name']);
                }
                $data[] = [
                    'id' => $v['id'],
                    'ocation_id' => $v['id'],
                    'classes_id' => join(" ", $this->getClassesIdByOcationId($v['id'])),
                    'parent' => $v['pid'] ? $v['pid'] : '#',
                    'name' => $v['name'],
                    'level' => $v['level'],
                    'type' => $v['type'],
                    'status' => $v['status'],
                    'haschild' => $v['haschild'],
                    'address' => $v['address'],
                    'weekdays' => $v['weekdays'],
                    'ocation_type' => $ocation_type,
                    'entvirt' => $entvirt,
                    'endtime' => $endtime,
                    'address_lv_octionlevel' => model("Ocation")->getAddress_lv_octionlevel_TextAttr($v['address_lv_octionlevel']),
                    'school_location_type' => model("Ocation")->getSchool_location_typeTextAttr($v['school_location_type']),
                ];
            }
            $total = count($data);
            $result = array("total" => $total, "rows" => $data);
            return json($result);
        }
        $this->assignconfig("relType", $relType);
        $this->assignconfig("relId", $relId);
        $this->assignconfig("cityId", $city_id);
        $this->assignconfig("schoolId", $school_id);
        return $this->view->fetch();
    }

    /**
     * 添加
     */
    public function add()
    {
        $relId = $this->request->get("relId") ? $this->request->get("relId") : $_SESSION['think']['admin']['rel_id'];
        $relType = $this->request->get("relType") ? $this->request->get("relType") : $_SESSION['think']['admin']['rel_type'];
        if ($this->request->isPost()) {
            $params = $this->request->post("row/a");
            if ($params) {
                if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
                    $params[$this->dataLimitField] = $this->auth->id;
                }
                try {
                    // 使用验证器验证数据
                    $validate = new \app\admin\validate\Ocation();
                    if (!$validate->scene('add')->check($params)) {
                        return json(['code' => 0, 'msg' => $validate->getError()]);
                    }
                    $datatime = date("Y-m-d H:i:s");
                    $params['create_time'] = $datatime;
                    unset($params['delete_time']);
                    unset($params['update_time']);
                    //                    if($_SESSION['think']['admin']['group_id']==2){
                    //                        $params['city_id']=$_SESSION['think']['admin']['city_id'];
                    //                    }
                    $params['pid'] = isset($params['pid']) ? preg_replace("/\#/", "0", $params['pid']) : '0';
                    if ($params['address_lv_octionlevel'] == 1) {
                        unset($params['starttime']);
                        unset($params['endtime']);
                    }
                    $params['update_time'] = (!array_key_exists("update_time", $params) || $params['update_time'] == "") ? date("Y-m-d H:i:s", time()) : date("Y-m-d H:i:s", strtotime($params['update_time']));
                    $params['delete_time'] = (!array_key_exists("delete_time", $params) || $params['delete_time'] == "") ? null : date("Y-m-d H:i:s", strtotime($params['delete_time']));
                    $params['weekdays'] = join(",", $params['weekdays']);
                    $params['disable_week_range'] = join(",", $params['disable_week_range']);
                    $params['disable_week_time'] = join(",", $params['disable_week_time']);
                    $params['daytime'] = join(",", $params['daytime']);

                    // 处理校内校外字段
                    if (isset($params['school_location_type']) && is_array($params['school_location_type'])) {
                        $params['school_location_type'] = join(",", $params['school_location_type']);
                    } else {
                        $params['school_location_type'] = '';
                    }

                    $params['rel_id'] = $relId;
                    $params['rel_type'] = $relType;



                    // 检查数据库表是否有school_location_type字段
                    try {
                        $tableInfo = \think\Db::query("SHOW COLUMNS FROM fa_ocation LIKE 'school_location_type'");
                        if (empty($tableInfo)) {
                            // 如果字段不存在，移除这个参数
                            unset($params['school_location_type']);
                        }
                    } catch (\Exception $e) {
                        unset($params['school_location_type']);
                    }

                    $result = $this->model->allowField(true)->save($params);
                    if ($result !== false) {
                        return json(['code' => 1, 'msg' => '添加成功']);
                    } else {
                        return json(['code' => 0, 'msg' => $this->model->getError()]);
                    }
                } catch (\think\exception\PDOException $e) {
                    return json(['code' => 0, 'msg' => $e->getMessage()]);
                } catch (\think\Exception $e) {
                    return json(['code' => 0, 'msg' => $e->getMessage()]);
                }
            }
            return json(['code' => 0, 'msg' => __('Parameter %s can not be empty', '')]);
        }
        $this->assign('admin', $_SESSION['think']['admin']);
        $this->assignconfig('admin', $_SESSION['think']['admin']);
        $this->assignconfig("relType", $relType);
        $this->assignconfig("relId", $relId);
        return $this->view->fetch();
    }

    /**
     * 编辑
     */
    public function edit($ids = NULL)
    {
        $row = $this->model->get($ids);
        $relId = $this->request->get("relId") ? $this->request->get("relId") : $_SESSION['think']['admin']['rel_id'];
        $relType = $this->request->get("relType") ? $this->request->get("relType") : $_SESSION['think']['admin']['rel_type'];
        if (!$row)
            return json(['code' => 0, 'msg' => __('No Results were found')]);

        $adminIds = $this->getDataLimitAdminIds();
        if (is_array($adminIds)) {
            if (!in_array($row[$this->dataLimitField], $adminIds)) {
                return json(['code' => 0, 'msg' => __('You have no permission')]);
            }
        }
        if ($this->request->isPost()) {
            $params = $this->request->post("row/a");
            if ($params) {
                try {
                    // 添加当前记录ID到参数中，用于验证时排除自身
                    $params['id'] = $ids;

                    // 使用验证器验证数据
                    $validate = new \app\admin\validate\Ocation();
                    if (!$validate->scene('edit')->check($params)) {
                        return json(['code' => 0, 'msg' => $validate->getError()]);
                    }
                    $datetime = date("Y-m-d H:i:s");
                    $params['update_time'] = $datetime;
                    $params['schedule_data'] = json_decode($params['schedule_data'], 1);
                    $result = []; // 初始化结果数组
                    if (!empty($params['schedule_data'])) {
                        foreach ($params['schedule_data'] as $item) {
                            if ($item == null || empty($item['daytime']) || empty($item['oindex'])) {
                                continue; // 跳过当前元素
                            }
                            $key = $item['daytime'] . '_' . $item['oindex'];
                            $result[$key] = $item;
                        }
                        $params['schedule_data'] = json_encode(array_values($result));
                    }
                    unset($params['delete_time']);
                    unset($params['create_time']);
                    //                    if($_SESSION['think']['admin']['group_id']==2){
                    //                        $params['city_id']=$_SESSION['think']['admin']['city_id'];
                    //                    }
                    $params['create_time'] = (!array_key_exists("create_time", $params) || $params['create_time'] == "") ? date("Y-m-d H:i:s", time()) : date("Y-m-d H:i:s", strtotime($params['create_time']));
                    $params['delete_time'] = (!array_key_exists("delete_time", $params) || $params['delete_time'] == "") ? null : date("Y-m-d H:i:s", strtotime($params['delete_time']));
                    $params['pid'] = isset($params['pid']) ? preg_replace("/\#/", "0", $params['pid']) : '0';
                    $params['weekdays'] = join(",", $params['weekdays']);
                    $params['disable_week_range'] = join(",", $params['disable_week_range']);
                    $params['disable_week_time'] = join(",", $params['disable_week_time']);
                    $params['daytime'] = join(",", $params['daytime']);

                    // 处理校内校外字段
                    if (isset($params['school_location_type']) && is_array($params['school_location_type'])) {
                        $params['school_location_type'] = join(",", $params['school_location_type']);
                    } else {
                        $params['school_location_type'] = '';
                    }

                    $params['rel_id'] = $relId;
                    $params['rel_type'] = $relType;




                    // 检查日期时间字段，如果为空或address_lv_octionlevel=1则移除，避免SQL错误
                    if ($params['address_lv_octionlevel'] == 1 || empty($params['starttime'])) {
                        unset($params['starttime']);
                    }
                    if ($params['address_lv_octionlevel'] == 1 || empty($params['endtime'])) {
                        unset($params['endtime']);
                    }

                    // 处理image字段的隐藏值，与classes一样处理
                    if (isset($params['image'])) {
                        $params['image'] = is_array($params['image']) ? json_encode($params['image'], JSON_UNESCAPED_UNICODE) : $params['image'];
                    }



                    // 强制更新所有字段，不管是否有变化
                    $result = $row->allowField(true)->save($params);
                    if ($result !== false) {
                        return json(['code' => 1, 'msg' => '编辑成功']);
                    } else {
                        return json(['code' => 0, 'msg' => $row->getError()]);
                    }
                } catch (\think\exception\PDOException $e) {
                    return json(['code' => 0, 'msg' => $e->getMessage()]);
                } catch (\think\Exception $e) {
                    return json(['code' => 0, 'msg' => $e->getMessage()]);
                }
            }
            return json(['code' => 0, 'msg' => __('Parameter %s can not be empty', '')]);
        }
        //如何发现数据中没有设置经纬度，则取子ocation的经纬度，子ocation的经纬度可能为空，则使用父ocation的经纬度
        $row = json_decode(json_encode($row), 1);
        if ($row['address'] == "") {
            $jwd = self::getCoordinates($row['id']);
            $row['longitude'] = $jwd['longitude'];
            $row['latitude'] = $jwd['latitude'];
            $row['address'] = $jwd['address'];
        }
        // 处理image字段的隐藏值，与classes一样处理
        if ($row["image"] != "") {
            $row["image"] = json_decode($row["image"]);
            if (is_string($row["image"])) {
                $row["image"] = json_decode($row["image"]);
            }
        } else {
            $row["image"] = [];
        }
        $row["image"] = json_encode($row["image"]); // 最后转换为JSON字符串传递给模板

        $this->assign('admin', $_SESSION['think']['admin']);
        $this->assignconfig('admin', $_SESSION['think']['admin']);
        $this->assignconfig('relId', $relId);
        $this->assignconfig('relType', $relType);
        $this->view->assign("row", $row);
        return $this->view->fetch();
    }

    /**
     * 添加
     */
    public
    function view($ids = NULL)
    {
        $row = $this->model->getRow($ids);
        $this->view->assign("row", $row);
        return $this->view->fetch();
    }

    public
    function lists($ids = NULL)
    {
        $where = "where 1=1";
        // 新增：只显示本级及下级
        $admin_id = $this->request->get('admin_id');
        if ($admin_id == null) {
            $admin_id = $_SESSION['think']['admin']['id'];
        }
        $filter_ids = [];
        if ($admin_id) {
            // 查找该管理员的ocation_id
            $admin = Db::name('admin')->where('id', $admin_id)->find();
            if ($admin && isset($admin['ocation_id']) && $admin['ocation_id']) {
                // 处理可能是逗号分隔的字符串
                $ocation_ids = is_string($admin['ocation_id']) ? explode(',', $admin['ocation_id']) : [$admin['ocation_id']];
                $filter_ids = [];
                $filter_ids = $this->model::getChildOcationIds($ocation_ids, true);
                // 确保所有ID都是整数，并去重
                $filter_ids = array_unique(array_map('intval', $filter_ids));
            } else {
                // 如果找不到ocation_id，则返回空数组
                $filter_ids = [];
            }
        }
        if ($_SESSION['think']['admin']['group_id'] != 1) {
            $where .= " and city_id='{$_SESSION['think']['admin']['city_id']}'";
        }
        if (isset($_REQUEST['addresslv_id']) && $_REQUEST['addresslv_id'] != "" && ($_SESSION['think']['admin']['group_id'] == "3" || $_SESSION['think']['admin']['group_id'] == "2")) {
            $where .= " and address_lv='{$_REQUEST['addresslv_id']}'";
        }
        if (isset($_REQUEST['addresslv_id']) && $_REQUEST['addresslv_id'] == "") {
            $where .= " and address_lv='{$_REQUEST['addresslv_id']}'";
        }
        if ($_SESSION['think']['admin']['group_id'] == 2 || $_SESSION['think']['admin']['group_id'] == 8) {
            $where .= " and city_id='{$_SESSION['think']['admin']['city_id']}'";
        }
        $relId = ($this->request->get("rel_id") > 0) ? $this->request->get("rel_id") : (isset($_SESSION['think']['admin']['rel_id']) ? $_SESSION['think']['admin']['rel_id'] : 0);
        $relType = ($this->request->get("rel_type") > 0) ? $this->request->get("rel_type") : (isset($_SESSION['think']['admin']['rel_type']) ? $_SESSION['think']['admin']['rel_type'] : '');

        $page = 1;
        $pagesize = 50;
        if ($this->request->isAjax()) {
            if ($this->request->request('keyField')) {
                $keyField = $this->request->request("keyField");
                $keyValue = $this->request->request("keyValue");
                $page = $this->request->request("pageNumber");
                $page = ($page == null) ? 1 : $page;
                $pagesize = 500;
                if ($keyValue != "") {
                    $nn = preg_split("/\,/", $keyValue);
                    for ($i = 0; $i < count($nn); $i++) {
                        $where .= " and $keyField='{$nn[$i]}'";
                    }
                }
            }
        }
        // 获取所有数据用于构建树形结构
        $sql = "select id,pid,name,address,address_lv_octionlevel,status,weigh from fa_ocation $where order by weigh desc,id asc";
        $list = db()->query($sql);

        // 递归查找并补全所有祖先节点，确保根节点一定在$list中,然后找出$filter_ids的最近的上级父节点
        $idToPid = [];
        $allIds = array_column($list, 'id');
        foreach ($list as $item) {
            $idToPid[$item['id']] = $item['pid'];
        }
        if (!function_exists('fetchAncestors')) {
            function fetchAncestors($id, &$idToPid, &$allIds, &$list)
            {
                if (!isset($idToPid[$id])) {
                    $node = Db::name('ocation')->where('id', $id)->find();
                    if ($node) {
                        $idToPid[$node['id']] = $node['pid'];
                        $allIds[] = $node['id'];
                        $list[] = $node;
                        if ($node['pid']) {
                            fetchAncestors($node['pid'], $idToPid, $allIds, $list);
                        }
                    }
                }
            }
        }
        foreach ($list as $item) {
            fetchAncestors($item['id'], $idToPid, $allIds, $list);
        }
        $allIds = array_unique($allIds);
        $list = array_values(array_column($list, null, 'id'));
        // 找到最近的有效父节点作为根节点
        if (!function_exists('findNearestCommonParent')) {
            function findNearestCommonParent($ids, $idToPid)
            {
                if (empty($ids)) {
                    return null;
                }

                // 构建每个节点到根的路径
                $paths = [];
                foreach ($ids as $id) {
                    $path = [];
                    $currentId = $id;
                    while (isset($idToPid[$currentId]) && $idToPid[$currentId]) {
                        $path[] = $currentId;
                        $currentId = $idToPid[$currentId];
                    }
                    $path[] = $currentId; // 添加根节点
                    $paths[$id] = array_reverse($path);
                }

                // 如果只有一个节点，直接返回其父节点
                if (count($paths) === 1) {
                    $path = reset($paths);
                    return count($path) > 1 ? $path[count($path) - 2] : $path[0];
                }

                // 找到所有路径中最短的长度
                $minLen = min(array_map('count', $paths));

                // 从最后一个共同祖先向下查找，直到找到第一个分叉点的父节点
                $lastCommon = null;
                for ($i = 0; $i < $minLen; $i++) {
                    $firstPath = reset($paths);
                    $val = $firstPath[$i];
                    $isCommon = true;

                    foreach ($paths as $path) {
                        if ($path[$i] !== $val) {
                            $isCommon = false;
                            break;
                        }
                    }

                    if (!$isCommon) {
                        // 返回最后一个共同节点 AAA
                        return $lastCommon ?? $val;
                    }
                    $lastCommon = $val;
                }

                // 如果所有节点都在同一条路径上，返回最深的共同节点
                return $lastCommon;
            }
        }

        $rootId = findNearestCommonParent($filter_ids, $idToPid);
        if (!$rootId) {
            $rootId = isset($_SESSION['think']['admin']['ocation_id']) ? $_SESSION['think']['admin']['ocation_id'] : null;
        }
        // 使用Tree类构建树形结构
        $tree = Tree::instance();
        $tree->init($list, 'pid');
        // 获取父节点信息
        $parentNodes = [];
        if ($rootId) {
            // 获取所有父级节点
            $parentNodes = $tree->getParents($rootId, false);
            // 如果需要包含父教学点信息，获取完整树结构
            if ($rootId > 0) {
                // 方案3：获取父节点及其所有子节点
                $currentNode = Db::name('ocation')->where('id', $rootId)->find();
                if ($currentNode && $currentNode['pid'] > 0) {
                    // 如果有父节点，以父节点为根获取树结构
                    $treeList = $tree->getTreeList($tree->getTreeArray($currentNode['pid']), 'name');
                } else if ($currentNode) {
                    // 如果没有父节点，以当前节点为根
                   $treeList = $tree->getTreeList($tree->getTreeArray($currentNode['pid']), 'name');
                } else {
                    // 如果找不到当前节点，获取完整树结构
                    $treeList = $tree->getTreeList($tree->getTreeArray(0), 'name');
                }
            } else {
                // rootId为0时，获取完整树结构
                $treeList = $tree->getTreeList($tree->getTreeArray(0), 'name');
            }

            // // 为父级节点添加特殊标记，以便在前端展示时区分
            // foreach ($parentNodes as &$parent) {
            //     // 为父节点添加层级信息和特殊标记
            //     $parent['spacer'] = '';
            //     $parent['name'] = $parent['name'] . ' (上级)';
            //     $parent['is_parent'] = true; // 添加标记表示这是父节点
            // }

            // 将父节点添加到树列表的前面
            //$treeList = array_merge($parentNodes, $treeList);
        } else {
            $treeList = [];
        }


        // 为每个节点添加层级信息
        foreach ($treeList as $key => &$item) {
            // 计算层级深度
            $level = substr_count($item['name'], '&nbsp;') / 4; // 每级4个&nbsp;
            $item['level'] = $level;

            // 清理name中的HTML标签，保留纯文本
            $item['name'] = strip_tags(str_replace('&nbsp;', '', $item['name']));

            // 添加parent字段
            // 修复：检查pid键是否存在
            $item['parent'] = (isset($item['pid']) && $item['pid'] != 0) ? $item['pid'] : '#';

            // 计算是否有子节点
            $childCount = 0;
            foreach ($list as $child) {
                if ($child['pid'] == $item['id']) {
                    $childCount++;
                }
            }
            $item['haschild'] = $childCount;

            // 添加其他必要字段
            $item['type'] = $childCount > 0 ? 'folder' : 'file';
            $item['status'] = isset($item['status']) ? ($item['status'] == 1 ? 'normal' : 'hidden') : 'normal';

            // 修改：使用正确的树形连接符
            $prefix = '';
            if ($level > 0 && $level < 3) {
                $prefix = str_repeat('│  ', (int)($level - 1) * 8);
                $prefix .= '&nbsp;&nbsp;&nbsp;&nbsp;';
            }
        }

        // 分页处理
        $total = count($treeList);
        $pagesize = 5000;
        if ($this->request->isAjax() && isset($page) && isset($pagesize)) {
            $treeList = array_slice($treeList, ($page - 1) * $pagesize, $pagesize);
        }

        // 检查是否是Bootstrap Table请求（通过参数判断）
        if ($this->request->isAjax() && ($this->request->has('offset') || $this->request->has('limit'))) {
            // Bootstrap Table格式
            // 修复：确保返回的是数组而不是对象
            echo json_encode(array("total" => $total, "rows" => array_values($treeList)), JSON_UNESCAPED_UNICODE);
        } else {
            // 下拉框格式（保持兼容性）
            // 修复：确保返回的是数组而不是对象
            echo json_encode(array("list" => array_values($treeList), "total" => $total), JSON_UNESCAPED_UNICODE);
        }
        exit;
    }


    public
    function lists_sq($ids = NULL)
    {
        $user=$this->auth->getUserInfo();

        $where = "where 1=1";
        // 新增：只显示本级及下级
        $admin_id = $this->request->get('admin_id');
        if ($admin_id == null) {
            $admin_id = $_SESSION['think']['admin']['id'];
        }
        $filter_ids = [];
        if ($admin_id) {
            // 查找该管理员的ocation_id
            $admin = Db::name('admin')->where('id', $admin_id)->find();
            if ($admin && isset($admin['ocation_id']) && $admin['ocation_id']) {
                // 处理可能是逗号分隔的字符串
                $ocation_ids = is_string($admin['ocation_id']) ? explode(',', $admin['ocation_id']) : [$admin['ocation_id']];
                $filter_ids = [];
                $filter_ids = $this->model::getChildOcationIds($ocation_ids, true);
                // 确保所有ID都是整数，并去重
                $filter_ids = array_unique(array_map('intval', $filter_ids));
            } else {
                // 如果找不到ocation_id，则返回空数组
                $filter_ids = [];
            }
        }
        if ($_SESSION['think']['admin']['group_id'] != 1) {
            $where .= " and city_id='{$_SESSION['think']['admin']['city_id']}'";
        }
        if (isset($_REQUEST['addresslv_id']) && $_REQUEST['addresslv_id'] != "" && ($_SESSION['think']['admin']['group_id'] == "3" || $_SESSION['think']['admin']['group_id'] == "2")) {
            $where .= " and address_lv='{$_REQUEST['addresslv_id']}'";
        }
        if (isset($_REQUEST['addresslv_id']) && $_REQUEST['addresslv_id'] == "") {
            $where .= " and address_lv='{$_REQUEST['addresslv_id']}'";
        }
        if ($_SESSION['think']['admin']['group_id'] == 2 || $_SESSION['think']['admin']['group_id'] == 8) {
            $where .= " and city_id='{$_SESSION['think']['admin']['city_id']}'";
        }
        $relId = ($this->request->get("rel_id") > 0) ? $this->request->get("rel_id") : (isset($_SESSION['think']['admin']['rel_id']) ? $_SESSION['think']['admin']['rel_id'] : 0);
        $relType = 2;

        $page = 1;
        $pagesize = 50;
        if ($this->request->isAjax()) {
            if ($this->request->request('keyField')) {
                $keyField = $this->request->request("keyField");
                $keyValue = $this->request->request("keyValue");
                $page = $this->request->request("pageNumber");
                $page = ($page == null) ? 1 : $page;
                $pagesize = 500;
                if ($keyValue != "") {
                    $nn = preg_split("/\,/", $keyValue);
                    for ($i = 0; $i < count($nn); $i++) {
                        $where .= " and $keyField='{$nn[$i]}'";
                    }
                }
            }
        }
        // 获取所有数据用于构建树形结构
        $sql = "SELECT id,pid,rel_type,NAME,address,address_lv_octionlevel,STATUS,weigh FROM fa_ocation WHERE 1=1 AND city_id='{$user['city_id']}' AND (rel_type=1  OR pid IN (SELECT pid FROM fa_ocation WHERE 1=1 AND city_id='2' AND ((rel_type=2 OR `address_lv_octionlevel`<=1) OR (rel_type=2 AND `pid`=0)) GROUP BY pid) OR `address_lv_octionlevel`=0) ORDER BY weigh DESC,id ASC";
        $list = db()->query($sql);

        // 递归查找并补全所有祖先节点，确保根节点一定在$list中,然后找出$filter_ids的最近的上级父节点
        $idToPid = [];
        $allIds = array_column($list, 'id');
        foreach ($list as $item) {
            $idToPid[$item['id']] = $item['pid'];
        }
        if (!function_exists('fetchAncestors')) {
            function fetchAncestors($id, &$idToPid, &$allIds, &$list)
            {
                if (!isset($idToPid[$id])) {
                    $node = Db::name('ocation')->where('id', $id)->find();
                    if ($node) {
                        $idToPid[$node['id']] = $node['pid'];
                        $allIds[] = $node['id'];
                        $list[] = $node;
                        if ($node['pid']) {
                            fetchAncestors($node['pid'], $idToPid, $allIds, $list);
                        }
                    }
                }
            }
        }
        foreach ($list as $item) {
            fetchAncestors($item['id'], $idToPid, $allIds, $list);
        }
        $allIds = array_unique($allIds);
        $list = array_values(array_column($list, null, 'id'));
        // 找到最近的有效父节点作为根节点
        if (!function_exists('findNearestCommonParent')) {
            function findNearestCommonParent($ids, $idToPid)
            {
                if (empty($ids)) {
                    return null;
                }

                // 构建每个节点到根的路径
                $paths = [];
                foreach ($ids as $id) {
                    $path = [];
                    $currentId = $id;
                    while (isset($idToPid[$currentId]) && $idToPid[$currentId]) {
                        $path[] = $currentId;
                        $currentId = $idToPid[$currentId];
                    }
                    $path[] = $currentId; // 添加根节点
                    $paths[$id] = array_reverse($path);
                }

                // 如果只有一个节点，直接返回其父节点
                if (count($paths) === 1) {
                    $path = reset($paths);
                    return count($path) > 1 ? $path[count($path) - 2] : $path[0];
                }

                // 找到所有路径中最短的长度
                $minLen = min(array_map('count', $paths));

                // 从最后一个共同祖先向下查找，直到找到第一个分叉点的父节点
                $lastCommon = null;
                for ($i = 0; $i < $minLen; $i++) {
                    $firstPath = reset($paths);
                    $val = $firstPath[$i];
                    $isCommon = true;

                    foreach ($paths as $path) {
                        if ($path[$i] !== $val) {
                            $isCommon = false;
                            break;
                        }
                    }

                    if (!$isCommon) {
                        // 返回最后一个共同节点 AAA
                        return $lastCommon ?? $val;
                    }
                    $lastCommon = $val;
                }

                // 如果所有节点都在同一条路径上，返回最深的共同节点
                return $lastCommon;
            }
        }

        $rootId = findNearestCommonParent($filter_ids, $idToPid);
        $rootId=1;
        if (!$rootId) {
            $rootId = isset($_SESSION['think']['admin']['ocation_id']) ? $_SESSION['think']['admin']['ocation_id'] : null;
        }
        // 使用Tree类构建树形结构
        $tree = Tree::instance();
        $tree->init($list, 'pid');

        // 获取父节点信息
        $parentNodes = [];
        if ($rootId) {
            // 获取所有父级节点
            $parentNodes = $tree->getParents($rootId, false);

            // 如果需要包含父教学点信息，获取完整树结构
            if ($rootId > 0) {
                // 方案3：获取父节点及其所有子节点
                $currentNode = Db::name('ocation')->where('id', $rootId)->find();

                if ($currentNode && $currentNode['pid'] > 0) {
                    // 如果有父节点，以父节点为根获取树结构

                    $treeList = $tree->getTreeList($tree->getTreeArray($currentNode['pid']), 'name');

                } else {

                    // 如果没有父节点，以当前节点为根
                    $treeList = $tree->getTreeList($tree->getTreeArray($rootId), 'NAME');

                }
            } else {
                // rootId为0时，获取完整树结构
                $treeList = $tree->getTreeList($tree->getTreeArray(0), 'name');
            }

            // // 为父级节点添加特殊标记，以便在前端展示时区分
            // foreach ($parentNodes as &$parent) {
            //     // 为父节点添加层级信息和特殊标记
            //     $parent['spacer'] = '';
            //     $parent['name'] = $parent['name'] . ' (上级)';
            //     $parent['is_parent'] = true; // 添加标记表示这是父节点
            // }

            // 将父节点添加到树列表的前面
            //$treeList = array_merge($parentNodes, $treeList);
        } else {
            $treeList = [];
        }


        // 为每个节点添加层级信息
        foreach ($treeList as $key => &$item) {
            // 计算层级深度
            if(array_key_exists('NAME',$item)){
                $level = substr_count($item['NAME'], '&nbsp;') / 4; // 每级4个&nbsp;
            }elseif(array_key_exists('name',$item)){
                $level = substr_count($item['name'], '&nbsp;') / 4; // 每级4个&nbsp;
            }

            $item['level'] = $level;

            // 清理name中的HTML标签，保留纯文本
            $item['name'] = strip_tags(str_replace('&nbsp;', '', $item['NAME']));

            // 添加parent字段
            // 修复：检查pid键是否存在
            $item['parent'] = (isset($item['pid']) && $item['pid'] != 0) ? $item['pid'] : '#';

            // 计算是否有子节点
            $childCount = 0;
            foreach ($list as $child) {
                if ($child['pid'] == $item['id']) {
                    $childCount++;
                }
            }
            $item['haschild'] = $childCount;

            // 添加其他必要字段
            $item['type'] = $childCount > 0 ? 'folder' : 'file';
            $item['status'] = isset($item['status']) ? ($item['status'] == 1 ? 'normal' : 'hidden') : 'normal';

            // 修改：使用正确的树形连接符
            $prefix = '';
            if ($level > 0 && $level < 3) {
                $prefix = str_repeat('│  ', (int)($level - 1) * 8);
                $prefix .= '&nbsp;&nbsp;&nbsp;&nbsp;';
            }
            $item['name']= $prefix . $item['name']."({$item['id']})";
        }

        // 分页处理
        $total = count($treeList);
        $pagesize = 5000;
        if ($this->request->isAjax() && isset($page) && isset($pagesize)) {
            $treeList = array_slice($treeList, ($page - 1) * $pagesize, $pagesize);
        }

        // 检查是否是Bootstrap Table请求（通过参数判断）
        if ($this->request->isAjax() && ($this->request->has('offset') || $this->request->has('limit'))) {
            // Bootstrap Table格式
            // 修复：确保返回的是数组而不是对象
            echo json_encode(array("total" => $total, "rows" => array_values($treeList)), JSON_UNESCAPED_UNICODE);
        } else {
            // 下拉框格式（保持兼容性）
            // 修复：确保返回的是数组而不是对象
            echo json_encode(array("list" => array_values($treeList), "total" => $total), JSON_UNESCAPED_UNICODE);
        }
        exit;
    }


    public
    function lists2($ids = NULL)
    {
        $where = "where 1=1";
        $relId = $this->request->get("relId") ? $this->request->get("relId") : $_SESSION['think']['admin']['rel_id'];
        $relType = $this->request->get("relType") ? $this->request->get("relType") : $_SESSION['think']['admin']['rel_type'];

        if (isset($relType)) {
            $m = model("Addresslv")->where("rel_type", "=", $relType)
                ->where("rel_id", "=", $relId)
                ->where("status", "=", 1);
            if ($_SESSION['think']['admin']['group_id'] == 2 || $_SESSION['think']['admin']['group_id'] == 8) {
                $m = $m->where("city_id", "=", $_SESSION['think']['admin']['city_id']);
            }
            if (isset($relType) && isset($relId) > 0) {
                $m = $m->where("rel_id", "=", $relId);
                $m = $m->where("rel_type", "=", $relType);
            }
            $r = $m->select();

            if ($relType == "1" || $_REQUEST['relType'] == "school") {
                $tablename = "School";
                $tableN = "eb_school";
            } else {
                $tablename = "Community";
                $tableN = "fa_community";
            }

            if ($relId != "") {
                if ($relId > 0) {
                    $m->where("rel_type", "=", $relType)->where("rel_id", "=", $relId);
                }
                $data = $m->select();
                $r_name = model("Addresslv")->field("id,name")->where("id", "=", $relId)->select();
                if (empty($data) && !empty($r_name) && isset($r_name[0]) && isset($r_name[0]['name'])) {
                    $data = array(
                        "pid" => 0,
                        "name" => $r_name[0]['name'],
                        "title" => $r_name[0]['name'],
                        "ismenu" => 0,
                        "status" => 1,
                        "create_time" => date("Y-m-d H:i:s"),
                        "city_id" => $_SESSION['think']['admin']['city_id'],
                        "rel_id" => $relId,
                        "rel_type" => $relType,
                    );
                    model("Ocation")->create($data);
                }
            }
            $m = model("Ocation")->where("rel_type", "=", $relType);
            if ($relId > 0) {
                $m->where("rel_id", "=", $relId);
            }
            function week($week)
            {
                switch ($week) {
                    case "周一":
                        return 1;
                        break;
                    case "周二":
                        return 2;
                        break;
                    case "周三":
                        return 3;
                        break;
                    case "周四":
                        return 4;
                        break;
                    case "周五":
                        return 5;
                        break;
                    case "周六":
                        return 6;
                        break;
                    case "周日":
                        return 7;
                        break;
                }
                return 0;
            }

            function find_daytime($oindex, $schedule_data)
            {
                // 检查 $schedule_data 是否为数组
                if (!is_array($schedule_data)) {
                    return null; // 或者抛出异常
                }

                // 检查 $oindex 是否存在于 $schedule_data 中
                foreach ($schedule_data as $item) {
                    if ($item['oindex'] == $oindex) {
                        return $item["start_time"] . "-" . $item["end_time"];
                    }
                }
                return null;
            }

            $data = $m->select();
            //print_r($m->getLastSql());exit;
            $tree = Tree::instance();
            $tree->init($data, 'pid');
            $pid = 0;
            $arr = $tree->getTreeList($tree->getTreeArray($pid), 'name');

            // 准备三个选项卡的数据
            $allData = array();
            $schoolData = array(); // 校内
            $outsideData = array(); // 校外

            for ($i = 0; $i < count($arr); $i++) {
                $v = $arr[$i]->toarray();
                $schedule_data = isset($v['schedule_data']) ? json_decode($v['schedule_data'], 1) : [];
                $data2 = collection(model("Classroomeplan")->alias("r")->join("eb_classes c", "c.id=r.classes_id")->where("r.status", "1")->where("c.status", "1")->where("r.ocation_id", $v['id'])->select())->toArray();
                $newarr = array();
                foreach ($data2 as $k => $vv) {
                    $newarr[$v['id']][$vv['week']][] = $vv['daytime'];
                }
                $v['already_schedule'] = json_encode($newarr);
                if (!empty($schedule_data)) {
                    $newarr = array();
                    $nn33 = explode(",", $v["disable_week_time"]);
                    for ($j = 0; $j < count($nn33); $j++) {
                        $week2 = week(substr($nn33[$j], 0, 6));
                        $oindex = preg_replace("/节/", "", substr($nn33[$j], 7));
                        $daytime2 = find_daytime($oindex, $schedule_data);
                        $newarr[$v['id']][$week2][] = $daytime2;
                    }
                }
                $v['disable_week_time'] = json_encode($newarr);

                // 添加校内校外数字转中文的代码
                $schoolLocationTypeText = '';
                if (isset($v['school_location_type'])) {
                    switch ($v['school_location_type']) {
                        case '1':
                            $schoolLocationTypeText = '<span style="background-color: #1890ff; color: white; padding: 2px 5px; border-radius: 3px;">校内</span>';
                            break;
                        case '2':
                            $schoolLocationTypeText = '<span style="background-color: #52c41a; color: white; padding: 2px 5px; border-radius: 3px;">校外</span>';
                            break;
                        default:
                            $schoolLocationTypeText = '';
                    }
                }

                $item = [
                    'id' => $v['id'],
                    'parent' => $v['pid'] ? $v['pid'] : '#',
                    'name' => $v['name'],
                    'level' => $v['level'],
                    'type' => $v['type'],
                    'status' => $v['status'],
                    'haschild' => $v['haschild'],
                    'address_lv_octionlevel' => $v['address_lv_octionlevel'],
                    'schedule_data' => $v['schedule_data'],
                    'weekdays' => $v['weekdays'],
                    'already_schedule' => $v['already_schedule'],
                    'disable_week_time' => $v['disable_week_time'],
                    'school_location_type_text' => $schoolLocationTypeText,
                    'school_location_type' => $v['school_location_type'] // 保留原始值用于过滤
                ];

                // 添加到全部数据
                $allData[] = $item;

                // 根据school_location_type分类添加到对应选项卡数据
                if (isset($v['school_location_type']) && $v['school_location_type'] == '1') {
                    $schoolData[] = $item;
                } elseif (isset($v['school_location_type']) && $v['school_location_type'] == '2') {
                    $outsideData[] = $item;
                }
            }
        } elseif (isset($relType) && $relType == 2) {
            $where = "where 1=1";
            $m = model("Addresslv")->where("rel_type", "=", $relType)
                ->where("rel_id", "=", $relId)
                ->where("status", "=", 1);
            if ($_SESSION['think']['admin']['group_id'] == 2 || $_SESSION['think']['admin']['group_id'] == 8) {
                $m = $m->where("city_id", "=", $_SESSION['think']['admin']['city_id']);
            }
            if (isset($_SESSION['think']['admin']['rel_type']) && $_SESSION['think']['admin']['rel_id'] > 0) {
                $m = $m->where("rel_id", "=", $_SESSION['think']['admin']['rel_id']);
            }
            $r = $m->select();

            if ($relType == "1" || $relType == "school") {
                $tablename = "School";
                $tableN = "eb_school";
            } else {
                $tablename = "Community";
                $tableN = "fa_community";
            }

            if ($relId != "") {
                $m = model("Ocation")->where("rel_type", "=", $relType);
                if ($relId > 0) {
                    $m->where("rel_id", "=", $relId);
                }
                $data = $m->select();
                $r_name = model("Addresslv")->field("id,name")->where("id", "=", $relId)->select();
                if (empty($data) && !empty($r_name)) {
                    $data = array(
                        "pid" => 0,
                        "name" => $r_name[0]['name'],
                        "title" => $r_name[0]['name'],
                        "ismenu" => 0,
                        "status" => 1,
                        "create_time" => date("Y-m-d H:i:s"),
                        "city_id" => $_SESSION['think']['admin']['city_id'],
                        "rel_id" => $relId,
                        "rel_type" => $relType,
                    );
                    model("Ocation")->create($data);
                }
            }
            $m = model("Ocation")->where("rel_type", "=", $relType);
            if ($relId > 0) {
                $m->where("rel_id", "=", $relId);
            }
            $data = $m->select();
            $tree = Tree::instance();
            $tree->init($data, 'pid');
            $pid = 0;
            $arr = $tree->getTreeList($tree->getTreeArray($pid), 'name');

            // 准备三个选项卡的数据
            $allData = array();
            $schoolData = array(); // 校内
            $outsideData = array(); // 校外

            for ($i = 0; $i < count($arr); $i++) {
                $v = $arr[$i]->toarray();
                $schedule_data = isset($v['schedule_data']) ? json_decode($v['schedule_data'], 1) : [];
                $data2 = collection(model("Classroomeplan")->alias("r")->join("eb_classes c", "c.id=r.classes_id")->where("r.status", "1")->where("c.status", "1")->where("r.ocation_id", $v['id'])->select())->toArray();
                $newarr = array();
                foreach ($data2 as $k => $vv) {
                    $newarr[$v['id']][$vv['week']][] = $vv['daytime'];
                }
                $v['already_schedule'] = json_encode($newarr);
                if (!empty($schedule_data)) {
                    $newarr = array();
                    $nn33 = explode(",", $v["disable_week_time"]);
                    for ($j = 0; $j < count($nn33); $j++) {
                        $week2 = week(substr($nn33[$j], 0, 6));
                        $oindex = preg_replace("/节/", "", substr($nn33[$j], 7));
                        $daytime2 = find_daytime($oindex, $schedule_data);
                        $newarr[$v['id']][$week2][] = $daytime2;
                    }
                }
                $v['disable_week_time'] = json_encode($newarr);

                $item = [
                    'id' => $v['id'],
                    'parent' => $v['pid'] ? $v['pid'] : '#',
                    'name' => $v['name'],
                    'level' => $v['level'],
                    'type' => $v['type'],
                    'status' => $v['status'],
                    'haschild' => $v['haschild'],
                    'address_lv_octionlevel' => $v['address_lv_octionlevel'],
                    'schedule_data' => $v['schedule_data'],
                    'weekdays' => $v['weekdays'],
                    'already_schedule' => $v['already_schedule'],
                    'disable_week_time' => $v['disable_week_time'],
                ];

                // 添加到全部数据
                $allData[] = $item;

                // 根据school_location_type分类添加到对应选项卡数据
                if (isset($v['school_location_type']) && $v['school_location_type'] == '1') {
                    $schoolData[] = $item;
                } elseif (isset($v['school_location_type']) && $v['school_location_type'] == '2') {
                    $outsideData[] = $item;
                }
            }
        }

        // 返回三个选项卡的数据
        echo json_encode([
            "all" => ["list" => $allData, "total" => count($allData)],
            "school" => ["list" => $schoolData, "total" => count($schoolData)],
            "outside" => ["list" => $outsideData, "total" => count($outsideData)]
        ], JSON_UNESCAPED_UNICODE);
        exit;
    }


    function lists_community()
    {
        $relType = $this->request->param("rel_type");
        $relId = $this->request->param("rel_id");
        $data = model("Ocation")->field("id,name")
            ->where("address_lv_octionlevel", "=", 2)
            ->where("status", "=", 1)
            ->where("rel_type", "=", 2)
            ->where("city_id", "=", $_SESSION['think']['admin']['city_id'])
            ->select();
        //echo model("Community")->getLastSql();
        return json(['code' => 1, 'msg' => '添加成功!', 'list' => $data]);
    }

    public
    function status($ids = '')
    {
        $ids = $this->request->post('ids');
        if (empty($ids)) {
            return json(['code' => 0, 'msg' => '没有选中!']);
        }
        try {
            $result = $this->model->where("id", "=", $ids)->field("status")->find();
            $v = $result->status == 1 ? 0 : 1;
            $this->model->where("id", "=", $ids)->update(["status" => $v]);
            return json(['code' => 1, 'msg' => '切换成功!']);
        } catch (\Exception $e) {
            return json(['code' => 0, 'msg' => '切换失败!' . $e->getMessage()]);
        }
    }

    public
    function changeStatus($ids = '')
    {
        $ids = $this->request->post('ids');
        if (empty($ids)) {
            return json(['code' => 0, 'msg' => '没有选中!']);
        }
        try {
            $result = $this->model->where("id", "=", $ids)->field("status")->find();
            $v = $result->status == 1 ? 0 : 1;
            $this->model->where("id", "=", $ids)->update(["status" => $v]);
            return json(['code' => 1, 'msg' => '切换成功!']);
        } catch (\Exception $e) {
            return json(['code' => 0, 'msg' => '切换失败!' . $e->getMessage()]);
        }
    }

    public
    function del($ids = null)
    {
        if (false === $this->request->isPost()) {
            return json(['code' => 0, 'msg' => __("Invalid parameters")]);
        }
        $ids = $ids ?: $this->request->post("ids");
        if (empty($ids)) {
            return json(['code' => 0, 'msg' => __('Parameter %s can not be empty', 'ids')]);
        }
        $pk = $this->model->getPk();
        $adminIds = $this->getDataLimitAdminIds();
        if (is_array($adminIds)) {
            $this->model->where($this->dataLimitField, 'in', $adminIds);
        }
        $list = $this->model->where($pk, 'in', $ids)->where("pid", '<>', 0)->select();

        $count = 0;
        Db::startTrans();
        try {
            foreach ($list as $item) {
                // 软删除：设置delete_time字段
                $count += $item->save(['delete_time' => time(),'status'=>0]);
            }
            Db::commit();
        } catch (\PDOException | \Exception $e) {
            Db::rollback();
            return json(['code' => 0, 'msg' => $e->getMessage()]);
        }
        if ($count) {
            return json(['code' => 1, 'msg' => '删除成功']);
        }
        return json(['code' => 0, 'msg' => __('No rows were deleted')]);
    }

    public
    function export()
    {
        // 获取数据
        $list = $this->model->select();

        // 设置导出文件名
        $filename = 'your_filename_' . date('YmdHis');

        // 设置表头
        $headers = [
            'ID',
            'Name',
            'Create Time'
        ];

        // 设置数据
        $data = [];
        foreach ($list as $item) {
            $data[] = [
                $item['id'],
                $item['name'],
                $item['create_time'],
            ];
        }

        // 调用导出方法
        $this->exportExcel($filename, $headers, $data);
    }

    /**
     * 检查并修复教学点层级结构
     * 如果某个三级教学点或教室是直接从一级教学点继承的（缺少二级教学点）
     * 则在其之前插入一个二级教学点，并更新其父级关系
     */
    public
    function fixTeachingPointHierarchy()
    {
        // 设置过滤方法
        $this->request->filter(['strip_tags']);

        try {
            // 查找所有三级教学点或教室，它们的父级是一级教学点
            $problematicPoints = $this->model
                ->alias('o1')
                ->join('fa_ocation o2', 'o1.pid = o2.id')
                ->where('o1.address_lv_octionlevel', 'in', [3, 4]) // 三级教学点或教室
                ->where('o2.address_lv_octionlevel', '=', 1) // 父级是一级教学点
                ->field('o1.*, o2.name as parent_name, o2.id as parent_id')
                ->select();

            $count = 0;
            $processedParents = []; // 记录已处理过的一级教学点，避免重复创建二级教学点

            foreach ($problematicPoints as $point) {
                // 检查这个一级教学点是否已经创建了二级教学点
                if (isset($processedParents[$point['parent_id']])) {
                    $newLevel2Id = $processedParents[$point['parent_id']];
                } else {
                    // 检查是否已存在同名的二级教学点
                    $existingLevel2 = $this->model
                        ->where('pid', $point['parent_id'])
                        ->where('name', $point['parent_name'] . '中心教学点')
                        ->where('address_lv_octionlevel', 2)
                        ->find();

                    if ($existingLevel2) {
                        $newLevel2Id = $existingLevel2['id'];
                    } else {
                        // 为一级教学点创建一个新的二级教学点
                        $newLevel2Point = [
                            'pid' => $point['parent_id'],
                            'name' => $point['parent_name'] . '中心教学点',
                            'title' => $point['parent_name'] . '中心教学点',
                            'address_lv_octionlevel' => 2, // 设置为二级教学点
                            'rel_id' => $point['rel_id'],
                            'rel_type' => $point['rel_type'],
                            'status' => 1,
                            'create_time' => date('Y-m-d H:i:s'),
                            'update_time' => date('Y-m-d H:i:s')
                        ];

                        // 再次检查是否已存在相同的二级教学点（防止并发问题）
                        $existingLevel2Again = $this->model
                            ->where('pid', $point['parent_id'])
                            ->where('name', $point['parent_name'] . '中心教学点')
                            ->where('address_lv_octionlevel', 2)
                            ->find();

                        if ($existingLevel2Again) {
                            // 如果在我们准备插入前已经有了相同的记录，就使用它
                            $newLevel2Id = $existingLevel2Again['id'];
                        } else {
                            // 插入新的二级教学点
                            $id = $this->model->insertUpdate($newLevel2Point, ["name", "rel_type", "rel_id"]);
                            $newLevel2Id = $id;
                        }
                    }

                    // 记录已处理过的一级教学点
                    $processedParents[$point['parent_id']] = $newLevel2Id;
                }

                // 检查当前教学点的父级是否已经是二级教学点
                if ($point['pid'] != $newLevel2Id) {
                    // 更新原三级教学点或教室的父级为新的二级教学点
                    $updateData = [
                        'pid' => $newLevel2Id
                    ];

                    // 如果是三级教学点，将其改为教室（级别4）
                    if ($point['address_lv_octionlevel'] == 3) {
                        $updateData['address_lv_octionlevel'] = 4;
                    }

                    // 使用原始方法进行更新
                    $updatePoint = $this->model->get($point['id']);
                    if ($updatePoint) {
                        $updatePoint->pid = $newLevel2Id;
                        if ($point['address_lv_octionlevel'] == 3) {
                            $updatePoint->address_lv_octionlevel = 4;
                        }
                        $result = $updatePoint->save();
                        if ($result !== false) {
                            $count++;
                        }
                    }
                }
            }
            // 返回成功结果，使用标准的 FastAdmin 成功响应格式
            return json(['code' => 1, 'msg' => '成功修复 ' . $count . ' 个教学点的层级结构', 'data' => null]);
        } catch (\Exception $e) {
            // 返回错误结果，使用标准的 FastAdmin 错误响应格式
            return json(['code' => 0, 'msg' => '修复失败: ' . $e->getMessage(), 'data' => null]);
        }
    }

    protected
    function exportExcel($filename, $headers, $data)
    {
        // 创建一个新的Spreadsheet对象
        $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();

        // 添加标题，并合并A1到C1单元格，设置居中
        $title = 'Your Title Here';  // 替换为实际的标题文本
        $sheet->mergeCells('A1:C1');
        $sheet->setCellValue('A1', $title);
        $sheet->getStyle('A1')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
        $sheet->getStyle('A1')->getFont()->setBold(true);

        // 设置表头
        $sheet->fromArray($headers, null, 'A2');

        // 设置数据
        $sheet->fromArray($data, null, 'A3');

        // 设置表头颜色为#ccc
        $sheet->getStyle('A2:C2')->getFill()
            ->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
            ->getStartColor()->setARGB('FFCCCCCC');  // #ccc in ARGB format

        // 启用筛选功能
        $sheet->setAutoFilter('A2:C2');

        // 设置列宽为内容自适应
        foreach (range('A', $sheet->getHighestColumn()) as $column) {
            $sheet->getColumnDimension($column)->setAutoSize(true);
        }

        // 设置响应头
        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment;filename="' . $filename . '.xlsx"');
        header('Cache-Control: max-age=0');

        // 输出文件
        $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx');
        $writer->save('php://output');
        exit;
    }

    /**
     * 检查教学点名称是否重复
     * 用于前端实时验证
     */
    public
    function checkName()
    {
        $name = $this->request->post('name', '');
        $pid = $this->request->post('pid', 0);
        $id = $this->request->post('id', 0);

        if (empty($name)) {
            return json(['code' => 0, 'msg' => '教学点名称不能为空']);
        }

        // 检查名称长度
        if (mb_strlen($name, 'utf-8') < 2 || mb_strlen($name, 'utf-8') > 50) {
            return json(['code' => 0, 'msg' => '教学点名称长度必须在2-50个字符之间']);
        }

        // 构建查询条件
        $where = [
            'name' => $name,
            'pid' => $pid,
            'status' => ['neq', -1] // 排除已删除的记录
        ];

        // 如果是编辑操作，排除当前记录
        if ($id > 0) {
            $where['id'] = ['neq', $id];
        }

        $count = Db::name('ocation')->where($where)->count();

        if ($count > 0) {
            return json(['code' => 0, 'msg' => '在当前父级下已存在同名的教学点，请更换名称']);
        }

        return json(['code' => 1, 'msg' => '教学点名称可以使用']);
    }

    public function listsusers($ids = NULL)
    {
        $where = "where 1=1";
        // 新增：只显示本级及下级
        $ocation_id = isset($_SESSION['think']['admin']['ocation_id']) ? $_SESSION['think']['admin']['ocation_id'] : null;

        $filter_ids = [];
        if ($ocation_id) {
            // 处理可能是逗号分隔的字符串
            $ocation_ids = is_string($ocation_id) ? explode(',', $ocation_id) : [$ocation_id];
            $filter_ids = [];
            foreach ($ocation_ids as $oid) {
                if (!empty($oid)) {
                    // 获取子节点
                    $children = $this->getChildOcationIds($oid, false);
                    $filter_ids = array_merge($filter_ids, $children);
                    // 添加当前节点
                    $filter_ids[] = $oid;
                }
            }
            // 确保所有ID都是整数，并去重
            $filter_ids = array_unique(array_map('intval', $filter_ids));
        }
        if ($_SESSION['think']['admin']['group_id'] != 1) {
            $where .= " and city_id='{$_SESSION['think']['admin']['city_id']}'";
        }
        if (isset($_REQUEST['addresslv_id']) && $_REQUEST['addresslv_id'] != "" && ($_SESSION['think']['admin']['group_id'] == "3" || $_SESSION['think']['admin']['group_id'] == "2")) {
            $where .= " and address_lv='{$_REQUEST['addresslv_id']}'";
        }
        if (isset($_REQUEST['addresslv_id']) && $_REQUEST['addresslv_id'] == "") {
            $where .= " and address_lv='{$_REQUEST['addresslv_id']}'";
        }
        if ($_SESSION['think']['admin']['group_id'] == 2 || $_SESSION['think']['admin']['group_id'] == 8) {
            $where .= " and city_id='{$_SESSION['think']['admin']['city_id']}'";
        }
        $relId = $this->request->get("rel_id") ? $this->request->get("rel_id") : $_SESSION['think']['admin']['rel_id'];
        $relType = $this->request->get("rel_type") ? $this->request->get("rel_type") : $_SESSION['think']['admin']['rel_type'];

        $page = 1;
        $pagesize = 50;
        if ($this->request->isAjax()) {
            if ($this->request->request('keyField')) {
                $keyField = $this->request->request("keyField");
                $keyValue = $this->request->request("keyValue");
                $page = $this->request->request("pageNumber");
                $page = ($page == null) ? 1 : $page;
                $pagesize = $this->request->request("pageSize");
                $pagesize = ($pagesize == null) ? 10 : $pagesize;
                if ($keyValue != "") {
                    $nn = preg_split("/\,/", $keyValue);
                    for ($i = 0; $i < count($nn); $i++) {
                        $where .= " and $keyField='{$nn[$i]}'";
                    }
                }
            }
        }
        // 获取所有数据用于构建树形结构
        $sql = "select id,pid,name,address,address_lv_octionlevel,status,weigh from fa_ocation $where order by weigh desc,id asc";
        $list = db()->query($sql);

        // 递归查找并补全所有祖先节点，确保根节点一定在$list中,然后找出$filter_ids的最近的上级父节点
        $idToPid = [];
        $allIds = array_column($list, 'id');
        foreach ($list as $item) {
            $idToPid[$item['id']] = $item['pid'];
        }
        if (!function_exists('fetchAncestors')) {
            function fetchAncestors($id, &$idToPid, &$allIds, &$list)
            {
                if (!isset($idToPid[$id])) {
                    $node = Db::name('ocation')->where('id', $id)->find();
                    if ($node) {
                        $idToPid[$node['id']] = $node['pid'];
                        $allIds[] = $node['id'];
                        $list[] = $node;
                        if ($node['pid']) {
                            fetchAncestors($node['pid'], $idToPid, $allIds, $list);
                        }
                    }
                }
            }
        }
        foreach ($list as $item) {
            fetchAncestors($item['id'], $idToPid, $allIds, $list);
        }
        $allIds = array_unique($allIds);
        $list = array_values(array_column($list, null, 'id'));
        // 找到最近的有效父节点作为根节点
        if (!function_exists('findNearestCommonParent')) {
            function findNearestCommonParent($ids, $idToPid)
            {
                if (empty($ids)) {
                    return null;
                }

                // 构建每个节点到根的路径
                $paths = [];
                foreach ($ids as $id) {
                    $path = [];
                    $currentId = $id;
                    while (isset($idToPid[$currentId]) && $idToPid[$currentId]) {
                        $path[] = $currentId;
                        $currentId = $idToPid[$currentId];
                    }
                    $path[] = $currentId; // 添加根节点
                    $paths[$id] = array_reverse($path);
                }

                // 如果只有一个节点，直接返回其父节点
                if (count($paths) === 1) {
                    $path = reset($paths);
                    return count($path) > 1 ? $path[count($path) - 2] : $path[0];
                }

                // 找到所有路径中最短的长度
                $minLen = min(array_map('count', $paths));

                // 从最后一个共同祖先向下查找，直到找到第一个分叉点的父节点
                $lastCommon = null;
                for ($i = 0; $i < $minLen; $i++) {
                    $firstPath = reset($paths);
                    $val = $firstPath[$i];
                    $isCommon = true;

                    foreach ($paths as $path) {
                        if ($path[$i] !== $val) {
                            $isCommon = false;
                            break;
                        }
                    }

                    if (!$isCommon) {
                        // 返回最后一个共同节点
                        return $lastCommon;
                    }
                    $lastCommon = $val;
                }

                // 如果所有节点都在同一条路径上，返回最深的共同节点
                return $lastCommon;
            }
        }

        $rootId = findNearestCommonParent($filter_ids, $idToPid);
        if (!$rootId) {
            $rootId = $_SESSION['think']['admin']['ocation_id'];
        }
        // 使用Tree类构建树形结构
        $tree = Tree::instance();
        $tree->init($list, 'pid');
        // 获取父节点信息
        $parentNodes = [];
        if ($rootId) {
            // 获取所有父级节点
            $parentNodes = $tree->getParents($rootId, false);
            // 如果需要包含父教学点信息，获取完整树结构
            if ($rootId > 0) {
                // 方案3：获取父节点及其所有子节点
                $currentNode = Db::name('ocation')->where('id', $rootId)->find();
                if ($currentNode && $currentNode['pid'] > 0) {
                    // 如果有父节点，以父节点为根获取树结构
                    $treeList = $tree->getTreeList($tree->getTreeArray($currentNode['pid']), 'name');
                } else {
                    // 如果没有父节点，以当前节点为根
                    $treeList = $tree->getTreeList($tree->getTreeArray($rootId), 'name');
                }
            } else {
                // rootId为0时，获取完整树结构
                $treeList = $tree->getTreeList($tree->getTreeArray(0), 'name');
            }

            // // 为父级节点添加特殊标记，以便在前端展示时区分
            // foreach ($parentNodes as &$parent) {
            //     // 为父节点添加层级信息和特殊标记
            //     $parent['spacer'] = '';
            //     $parent['name'] = $parent['name'] . ' (上级)';
            //     $parent['is_parent'] = true; // 添加标记表示这是父节点
            // }

            // 将父节点添加到树列表的前面
            //$treeList = array_merge($parentNodes, $treeList);
        } else {
            $treeList = [];
        }


        // 为每个节点添加层级信息
        foreach ($treeList as $key => &$item) {
            // 计算层级深度
            $level = substr_count($item['name'], '&nbsp;') / 4; // 每级4个&nbsp;
            $item['level'] = (int)$level; // 明确转换为整数，避免浮点数精度问题

            // 清理name中的HTML标签，保留纯文本
            $item['name'] = strip_tags(str_replace('&nbsp;', '', $item['name']));

            // 添加parent字段
            // 修复：检查pid键是否存在
            $item['parent'] = (isset($item['pid']) && $item['pid'] != 0) ? $item['pid'] : '#';

            // 计算是否有子节点
            $childCount = 0;
            foreach ($list as $child) {
                if ($child['pid'] == $item['id']) {
                    $childCount++;
                }
            }

            // 根据需求：当address_lv_octionlevel为3或4时，查询该教学点下的班级学生作为子节点
            if ($item['address_lv_octionlevel'] == 4 || $item['address_lv_octionlevel'] == 3) {
                // 查询该教学点下的班级
                $classes = Db::name('eb_classes')
                    ->where('ocation_id', $item['id'])
                    ->where('status', 1)
                    ->select();

                // 为每个班级添加学生子节点
                foreach ($classes as $class) {
                    // 查询班级下的学生
                    $students = Db::name('user')
                        ->alias('u')
                        ->join('eb_class_student cu', 'u.id = cu.student_id')
                        ->where('cu.classes_id', $class['id'])
                        ->where('u.status', 'normal')
                        ->field('u.id,u.username,u.nickname')
                        ->select();

                    // 如果有学生，则标记该教学点有子节点
                    if (count($students) > 0) {
                        $childCount = 1; // 标记有子节点
                        break;
                    }
                }
            }

            $item['haschild'] = $childCount;

            // 添加其他必要字段
            $item['type'] = $childCount > 0 ? 'folder' : 'file';
            $item['status'] = $item['status'] == 1 ? 'normal' : 'hidden';
        }

        // 新增：为address_lv_octionlevel为3或4的节点添加学生子节点
        $newTreeList = [];
        foreach ($treeList as $item) {
            // 添加原始节点
            $newTreeList[] = $item;

            // 如果是3级或4级教学点，添加学生子节点
            if ($item['address_lv_octionlevel'] == 3 || $item['address_lv_octionlevel'] == 4) {
                // 查询该教学点下的班级
                $classes = Db::name('eb_classes')
                    ->where('ocation_id', $item['id'])
                    ->where('status', 1)
                    ->select();

                // 为每个班级添加学生子节点
                foreach ($classes as $class) {
                    // 查询班级下的学生
                    $students = Db::name('user')
                        ->alias('u')
                        ->join('eb_class_student cu', 'u.id = cu.student_id')
                        ->where('cu.classes_id', $class['id'])
                        ->where('u.status', 'normal')
                        ->field('u.id,u.username,u.nickname')
                        ->select();

                    // 为每个学生添加子节点
                    foreach ($students as $student) {
                        $newTreeList[] = [
                            'id' => 'student_' . $student['id'], // 使用特殊前缀避免ID冲突
                            'pid' => $item['id'],
                            // 修改学生姓名显示逻辑，优先显示昵称，没有昵称则显示用户名，都没有则显示"未命名用户"
                            'name' => "│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├─ <span style='color:green'>" . (!empty($student['nickname']) ? $student['nickname'] : (!empty($student['username']) ? $student['username'] : '未命名用户')) . "</span>",
                            'level' => (int)($item['level'] + 1), // 明确转换为整数
                            'parent' => $item['id'],
                            'haschild' => 0,
                            'type' => 'file',
                            'status' => 'normal',
                            'address_lv_octionlevel' => 5, // 特殊标记为学生节点
                            // 保留其他必要字段
                            'address' => '',
                            'weigh' => 0
                        ];
                    }
                }
            }
        }
        $treeList = $newTreeList;

        // 分页处理
        $total = count($treeList);
        if ($this->request->isAjax() && isset($page) && isset($pagesize)) {
            $treeList = array_slice($treeList, ($page - 1) * $pagesize, $pagesize);
        }

        // 检查是否是Bootstrap Table请求（通过参数判断）
        if ($this->request->isAjax() && ($this->request->has('offset') || $this->request->has('limit'))) {
            // Bootstrap Table格式
            // 修复：确保返回的是数组而不是对象
            echo json_encode(array("total" => $total, "rows" => array_values($treeList)), JSON_UNESCAPED_UNICODE);
        } else {
            // 下拉框格式（保持兼容性）
            // 修复：确保返回的是数组而不是对象
            echo json_encode(array("list" => array_values($treeList), "total" => $total), JSON_UNESCAPED_UNICODE);
        }
        exit;
    }

    /**
     * 回收站
     */
    public function recyclebin()
    {
        //设置过滤方法
        $this->request->filter(['strip_tags', 'trim']);
        if ($this->request->isAjax()) {
            //如果发送的来源是Selectpage，则转发到Selectpage
            if ($this->request->request('keyField')) {
                return $this->selectpage();
            }
            list($where, $sort, $order, $offset, $limit) = $this->buildparams();
            
            // 移除数据权限限制逻辑，直接查询已删除的记录
            $list = Db::name("Ocation")
                ->where('delete_time', 'not null')
                ->where($where)
                ->order($sort, $order)
                ->paginate($limit);
            $result = array("total" => $list->total(), "rows" => $list->items());
            return json($result);
        }
        return $this->view->fetch();
    }

    /**
     * 恢复
     */
public function restore($ids = null)
{
    $ids = $ids ?: $this->request->param("ids");
    if (empty($ids)) {
        $this->error(__("Parameter %s can not be empty", "ids"));
    }
    $pk = $this->model->getPk();

    // 修改这里：直接查询已删除的记录
try {
        // 批量更新，更高效
        $count = db::name("Ocation")
            ->where('id', 'in', $ids)
            ->update([
                'delete_time' => null,
                'status' => 1,
                'update_time' => date("Y-m-d H:i:s",time())
            ]);
            
        if ($count > 0) {
            $result = array("total" => 1, "msg"=>"恢复成功！","code"=>1);
            return json($result);
        } else {
            $this->error(__("No Results were found"));
        }
    } catch (PDOException $e) {
        $this->error($e->getMessage());
    } catch (\Exception $e) {
        $this->error($e->getMessage());
    }
}

    /**
     * 真实删除
     */
    public function destroy($ids = "")
    {
        if (!$this->request->isPost()) {
            $this->error(__("Invalid parameters"));
        }
        $ids = $ids ? $ids : $this->request->post("ids");
        if (empty($ids)) {
            $this->error(__("Parameter %s can not be empty", "ids"));
        }
        $pk = $this->model->getPk();
        $adminIds = $this->getDataLimitAdminIds();
        if (is_array($adminIds)) {
            $this->model->where($this->dataLimitField, 'in', $adminIds);
        }
        // 修改这里：直接查询已删除的记录
        $list = $this->model->where($pk, 'in', $ids)->where('delete_time', 'not null')->select();
        
        $count = 0;
        Db::startTrans();
        try {
            foreach ($list as $item) {
                // 真实删除记录
                $result = $item->delete();
                if ($result) {
                    $count++;
                }
            }
            Db::commit();
        } catch (PDOException $e) {
            Db::rollback();
            $this->error($e->getMessage());
        } catch (\Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        if ($count) {
            $this->success();
        } else {
            $this->error(__("No rows were updated"));
        }
    }
    
    /**
     * 获取社区班级信息
     * 根据教学点ID获取相关的班级管理员、班级头像和班级详细信息
     */
    public function getCommunityClassInfo()
    {
        // 只允许AJAX请求
        if (!$this->request->isAjax()) {
            return json(['code' => 0, 'msg' => '非法请求']);
        }

        // 获取参数
        $ocationId = $this->request->get('ocation_id', 0);
        
        // 验证参数
        if (empty($ocationId) || !is_numeric($ocationId)) {
            return json(['code' => 0, 'msg' => '参数错误']);
        }

        try {
            // 查询教学点信息
            $ocationInfo = Db::name('ocation')->where('id', $ocationId)->where('status', 1)->find();
            
            if (empty($ocationInfo)) {
                return json(['code' => 0, 'msg' => '未找到指定的教学点信息']);
            }

            // 初始化返回数据
            $data = [
                'class_admin' => '',
                'class_avatar' => '',
                'class_details' => ''
            ];

            // 尝试从相关表中获取班级信息
            // 使用fa_ocation_class表与ocation关联
            $classInfo = Db::name('fa_ocation_class')
                ->where('ocation_id', $ocationId)
                ->where('status', 1)
                ->find();

            if (!empty($classInfo)) {
                // 如果找到班级信息，填充数据
                // 获取管理员名称（需要关联admin表）
                $adminName = '';
                if (isset($classInfo['manager_id']) && !empty($classInfo['manager_id'])) {
                    $adminInfo = Db::name('admin')->where('id', $classInfo['manager_id'])->field('nickname')->find();
                    $adminName = $adminInfo ? $adminInfo['nickname'] : '';
                }
                
                $data['class_admin'] = $adminName;
                $data['class_avatar'] = isset($classInfo['cover']) ? $classInfo['cover'] : '';
                $data['class_details'] = isset($classInfo['description']) ? $classInfo['description'] : (isset($classInfo['name']) ? $classInfo['name'].'的详细信息' : '');
            } else {
                // 如果没有找到班级信息，使用教学点信息作为默认值
                $data['class_admin'] = isset($ocationInfo['contact']) ? $ocationInfo['contact'] : '';
                $data['class_avatar'] = isset($ocationInfo['image']) ? $ocationInfo['image'] : '';
                $data['class_details'] = isset($ocationInfo['description']) ? $ocationInfo['description'] : $ocationInfo['name'].'的详细信息';
            }

            return json(['code' => 1, 'msg' => '获取成功', 'data' => $data]);
        } catch (\Exception $e) {
            return json(['code' => 0, 'msg' => '获取信息失败: ' . $e->getMessage()]);
        }
    }
}
